#include <tcpsocket.hxx>
#include <myfilelog.hxx>
#include <loghelper.hxx>
#include <tcpbridgenet.hxx>
#include <was_api.h>
#include <utility.hxx>
#include <macro.hxx>
#include <bridgemessage.hxx>
#include "priv/auconn.hxx"

//For cout test.
#include <iostream>
using namespace std;

AuConn::AuConn(AuConnManager *manager, TcpSocket* remote, FileLog *filelog)
: Thread(),
_manager(manager),
_remote(remote),
_username(),
_shutdown_requested(false),
_filelog(filelog)
{
}

AuConn::~AuConn()
{
	if (_remote)
	{
		delete _remote;
		_remote = 0;
	}
}

void AuConn::Shutdown()
{
	_shutdown_requested=true;
}

void AuConn::HandleMsg(tBridgeMsg* bmsg)
{
	switch (bmsg->tom)
	{
	case E_WAS_MSG_ATTACK:
	case E_WAS_MSG_ATTACK_STOP:
    case E_WAS_MSG_REP_PROXIES:
		_manager->SendToAttackers(bmsg);
        break;
    case E_WAS_MSG_CLI_DISC: 
        _username = bmsg->GetData(E_WAS_TAG_ID_USER);
		APPENDMSGEX("AuConn "<<Id()<<" "<<_username<<" discovered.", 3);
        break;
    case E_WAS_MSG_REP_RESULTS:
        _manager->SendToAutoers(bmsg, this);
        break;
	default:
		APPENDMSGEX("AuConn "<<Id()<<" HandleMsg unknown tom "<<bmsg->tom<<"!!!", 3);
		break;
	}

	ReleaseBMsg(bmsg);
}

bool AuConn::HandleIn()
{
	return true;
}

bool AuConn::HandleOut(void)
{
	return false;
}

///
//get request and send it
void AuConn::Execute(Arg arg)
{
	APPENDMSGEX("AuConn: #"<<Id()<<" started.", 3);

	TcpBridgeNet* bridgenet = new TcpBridgeNet(_remote, _filelog);

	tBridgeMsg* bmsg;
	BridgeNet::tBridgeNetStatus res;
	while (!_shutdown_requested)
	{
		//HandleIn();
		if (0 < bridgenet->IsReadyForRead(10))
		{
			res=bridgenet->ReceiveMsg(&bmsg);
			switch(res)
			{
			case BridgeNet::eMsgAvailable:
				{
					// Processing of the message at the application level is performed here
					// within the same thread.
					//
					APPENDMSGEX("AuConn: #"<<Id()<<" received a message from "<<bridgenet->PeerHostAddress()<<":"<<bridgenet->PeerHostPort(), 3);

					HandleMsg(bmsg);
				}
				break;

			case BridgeNet::eMsgNotAvailable:
				{
					LOGWARNING("AuConn: #"<<Id()<<" received a not available.");
				}
				break;
			case BridgeNet::eEndOfConnectionReceived:
				{
					APPENDMSGEX("AuConn: #"<<Id()<<" received end of connection signal from peer.", 3);

					Shutdown();
				}
				break;
			case BridgeNet::eNetworkErrorReceived:
				{
					APPENDMSGEX("AuConn: #"<<Id()<<" received network error.", 3);
					Shutdown();

				}
				break;
			default:
				{
					APPENDMSGEX("AuConn:  #"<<Id()<<" unexpected returned value "<<res<<" from BridgeNet::ReceiveMsg.", 2);
				}
				break;
			} // switch(res)
		}

		//HandleOut();
		if (bridgenet->IsReadyForWrite() > 0)
		{
			bmsg = _out_que.Pop();

			if (bmsg)
			{
				if (!bridgenet->SendMsg(bmsg))
				{
					APPENDMSGEX("AuConn: #"<<Id()<<" failed to send message!!", 3);
				}
				else
					APPENDMSGEX("AuConn: #"<<Id()<<" message sent successfully", 3);

				ReleaseBMsg(bmsg);
				bmsg = NULL;
			}

		}

		Yield();
	}

	delete bridgenet;
	bridgenet = 0;

	APPENDMSGEX("AuConn: #"<<Id()<<" shutdowned.", 3);
}
void AuConn::SendMsg(tBridgeMsg* bmsg)
{
    _out_que.Push(bmsg);
}
